﻿using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace Autodesk.Revit.DB;

/// <summary>
/// Autodesk.Revit.DB.Document 的扩展方法
/// </summary>
public static class DocumentExtensions
{
    private static string GetTransactionName()
    {
        return new StackTrace(true).GetFrame(1)!.GetMethod()!.Name;
    }

    /// <summary>
    /// 创建一个事务组
    /// </summary>
    /// <param name="document"></param>
    /// <param name="transGroupName"></param>
    /// <returns></returns>
    public static TransactionGroup CreateTransactionGroup(this Document document, string transGroupName)
    {
        return new TransactionGroup(document, transGroupName);
    }

    /// <summary>
    /// 创建一个事务组
    /// </summary>
    /// <param name="document"></param>
    /// <returns></returns>
    public static TransactionGroup CreateTransactionGroup(this Document document)
    {
        return new TransactionGroup(document);
    }

    /// <summary>
    /// 创建一个事务
    /// </summary>
    /// <param name="document"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    public static Transaction CreateTransaction(this Document document, string name)
    {
        return new Transaction(document, name);
    }

    /// <summary>
    /// 创建一个事务
    /// </summary>
    /// <param name="document"></param>
    /// <returns></returns>
    public static Transaction CreateTransaction(this Document document)
    {
        return new Transaction(document);
    }

    /// <summary>
    /// 事务处理
    /// </summary>
    /// <param name="transaction"></param>
    private static void TransactionHandle(Transaction transaction)
    {
        switch (transaction.GetStatus())
        {
            case TransactionStatus.Uninitialized:
                break;
            case TransactionStatus.Started:
                transaction.Commit();
                break;
            case TransactionStatus.RolledBack:
                break;
            case TransactionStatus.Committed:
                break;
            case TransactionStatus.Pending:
                break;
            case TransactionStatus.Error:
                break;
            case TransactionStatus.Proceed:
                break;
        }
    }

    /// <summary>
    /// 自动执行提交事务函数
    /// </summary>
    /// <typeparam name="TResult">返回数据的类型</typeparam>
    /// <param name="document">revit数据文档</param>
    /// <param name="func"></param>
    /// <param name="transactionName">事务名称</param>
    /// <param name="isIgnoreWarning">是否忽略警告弹窗</param>
    /// <param name="isResolveFailure">是否阻止错误弹窗</param>
    /// <returns>func的返回对象</returns>
    public static TResult AutoTransaction<TResult>(this Document document,
                                                   Func<Transaction, TResult> func,
                                                   [CallerMemberName] string transactionName = "",
                                                   bool isIgnoreWarning = true,
                                                   bool isResolveFailure = false)
    {
        TResult result;
        transactionName = string.IsNullOrWhiteSpace(transactionName) ? GetTransactionName() : transactionName;
        using (var trans = new Transaction(document, transactionName))
        {
            trans.Start(isIgnoreWarning, isResolveFailure);

            result = func(trans);

            TransactionHandle(trans);
        }
        return result;
    }

    /// <summary>
    /// 自动执行提交事务函数
    /// </summary>
    /// <param name="document">revit数据文档</param>
    /// <param name="action"></param>
    /// <param name="transactionName">事务名称</param>
    /// <param name="isIgnoreWarning">是否忽略警告弹窗</param>
    /// <param name="isResolveFailure">是否阻止错误弹窗</param>
    public static void AutoTransaction(this Document document,
                                       Action<Transaction> action,
                                       [CallerMemberName] string transactionName = "",
                                       bool isIgnoreWarning = true,
                                       bool isResolveFailure = false)
    {
        _ = document.AutoTransaction<object>(t => { action(t); return null!; }, transactionName, isIgnoreWarning, isResolveFailure);
    }

    /// <summary>
    /// 自动执行提交事务函数
    /// </summary>
    /// <typeparam name="TResult">返回数据的类型</typeparam>
    /// <param name="document">revit数据文档</param>
    /// <param name="func"></param>
    /// <param name="transactionName">事务名称</param>
    /// <param name="isIgnoreWarning">是否忽略警告弹窗</param>
    /// <param name="isResolveFailure">是否阻止错误弹窗</param>
    /// <returns>func的返回对象</returns>
    public static TResult AutoTransaction<TResult>(this Document document,
                                                   Func<TResult> func,
                                                   [CallerMemberName] string transactionName = "",
                                                   bool isIgnoreWarning = true,
                                                   bool isResolveFailure = false)
    {
        return document.AutoTransaction(t => func(), transactionName, isIgnoreWarning, isResolveFailure);
    }

    /// <summary>
    /// 自动执行提交事务函数
    /// </summary>
    /// <param name="document">revit数据文档</param>
    /// <param name="action"></param>
    /// <param name="transactionName">事务名称</param>
    /// <param name="isIgnoreWarning">是否忽略警告弹窗</param>
    /// <param name="isResolveFailure">是否阻止错误弹窗</param>
    public static void AutoTransaction(this Document document,
                                       Action action,
                                       [CallerMemberName] string transactionName = "",
                                       bool isIgnoreWarning = true,
                                       bool isResolveFailure = false)
    {
        document.AutoTransaction(t => action(), transactionName, isIgnoreWarning, isResolveFailure);
    }

    /// <summary>
    /// 创建Autodesk.Revit.DB.FilteredElementCollector
    /// </summary>
    /// <param name="document"></param>
    /// <returns></returns>
    public static FilteredElementCollector GetElements(this Document document)
    {
        return new FilteredElementCollector(document);
    }

    /// <summary>
    /// 创建Autodesk.Revit.DB.FilteredElementCollector
    /// </summary>
    /// <param name="document"></param>
    /// <param name="viewId"></param>
    /// <returns></returns>
    public static FilteredElementCollector GetElements(this Document document, ElementId viewId)
    {
        return new FilteredElementCollector(document, viewId);
    }

    /// <summary>
    /// 创建Autodesk.Revit.DB.FilteredElementCollector
    /// </summary>
    /// <param name="document"></param>
    /// <param name="elementIds"></param>
    /// <returns></returns>
    public static FilteredElementCollector GetElements(this Document document, ICollection<ElementId> elementIds)
    {
        return new FilteredElementCollector(document, elementIds);
    }

    /// <summary>
    /// 创建根据Type查找元素的Autodesk.Revit.DB.FilteredElementCollector
    /// </summary>
    /// <param name="document"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static FilteredElementCollector GetElementsOfType(this Document document, Type type)
    {
        return new FilteredElementCollector(document).OfClass(type);
    }

    /// <summary>
    /// 创建根据BuiltInCategory查找元素的Autodesk.Revit.DB.FilteredElementCollector
    /// </summary>
    /// <param name="document"></param>
    /// <param name="builtInCategory"></param>
    /// <returns></returns>
    public static FilteredElementCollector GetElementsOfCategory(this Document document, BuiltInCategory builtInCategory)
    {
        return new FilteredElementCollector(document).OfCategory(builtInCategory);
    }
}
